/**   
 * @{#} CsvImporter.java Create on 2013-6-24 上午9:50:04   
 *   
 * Copyright (c) 2012 by Baidu.   
 */
package objtable.port;

import java.io.FileReader;
import java.io.FileWriter;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import javassist.compiler.NoFieldException;

import objtable.core.TableCenter;
import objtable.core.TableGenerator;
import objtable.struct.Row;

import org.supercsv.cellprocessor.FmtNumber;
import org.supercsv.cellprocessor.ParseDate;
import org.supercsv.cellprocessor.ParseDouble;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.ParseLong;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.CsvBeanWriter;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;

/**
 * @author <a href="mailto:zhangbo07@baidu.com">zhangbo07</a>
 * @version 1.0
 */

public class CsvPort {
	private CsvPort() {
	}

	public static List<Row> fromCsv(String objtablename, String csvfile,
			String fields, CsvPreference cp) {
		return fromCsv(objtablename, csvfile, fields, null, cp);
	}

	public static List<Row> fromCsv(String objtablename, String csvfile,
			String fields, CellProcessor[] cellPros, CsvPreference cp) {
		TableGenerator tg = TableCenter.getTable(objtablename);
		List<Row> result = fromCsv(tg, csvfile, fields, cellPros, cp);
		// 把数据放到数据中心
		TableCenter.putTableData(objtablename, result);
		return result;
	}

	public static List<Row> fromCsv(TableGenerator tg, String csvfile,
			String fields, CellProcessor[] cellPros, CsvPreference cp) {
		List<Row> result = new ArrayList<Row>(200);
		try {
			String[] field = fields.split(",");
			Class<Row> cls = tg.getRowClass();
			if (cellPros == null) {
				// 生成默认的cellpros
				cellPros = genDefaultPros(cls, field, false);
			}

			ICsvBeanReader re = new CsvBeanReader(new FileReader(csvfile), cp);
			Row r = null;
			// 字段要以class的为主
			String[] classfields = getClsField(cls, field);
			while ((r = re.read(cls, classfields, cellPros)) != null) {
				result.add(r);
			}
			re.close();

			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	private static String[] getClsField(Class<Row> cls, String[] field) {
		ArrayList<String> f = new ArrayList<String>(field.length);
		for (String s : field) {
			try {
				cls.getDeclaredField(s);
				f.add(s);
			} catch (Exception e) {
			}
		}
		String[] result = new String[f.size()];
		result = f.toArray(result);
		return result;
	}

	public static void toCsv(String tablename, String csvfile, String fields) {
		List<Row> rs = TableCenter.getTableData(tablename);
		toCsv(rs, csvfile, fields, null);
	}

	public static void toCsv(List<Row> rs, String csvfile, String fields,
			CellProcessor[] cellPros) {
		try {
			String[] field = fields.split(",");
			if (rs.size() > 0) {
				@SuppressWarnings("unchecked")
				Class<Row> cls = (Class<Row>) rs.get(0).getClass();
				if (cellPros == null) {
					// 生成默认的cellpros
					cellPros = genDefaultPros(cls, field, true);
				}

				ICsvBeanWriter writer = new CsvBeanWriter(new FileWriter(
						csvfile), CsvPreference.STANDARD_PREFERENCE);
				for (Row r : rs) {
					writer.write(r, field, cellPros);
				}
				writer.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static CellProcessor[] genDefaultPros(Class<Row> cls,
			String[] field, boolean isOutPut) throws SecurityException {
		CellProcessor[] result = new CellProcessor[field.length];
		int i = 0;
		for (String f : field) {
			try {
				Field fi = cls.getDeclaredField(f);
				if (fi.getType().getName().toLowerCase().contains("string")) {
					result[i++] = null;
				} else if (fi.getType().getName().toLowerCase().contains("int")) {
					result[i++] = new ParseInt();
				} else if (fi.getType().getName().toLowerCase()
						.contains("date")) {
					result[i++] = new ParseDate("yyyyMMdd");
				} else if (fi.getType().getName().toLowerCase()
						.contains("long")) {
					result[i++] = new ParseLong();
				} else if (fi.getType().getName().toLowerCase()
						.contains("double")) {
					if (isOutPut) {
						result[i++] = new ParseDouble(new FmtNumber(
								new DecimalFormat("0.00")));
					} else {
						result[i++] = new ParseDouble();
					}
				}
			} catch (NoSuchFieldException ex) {
				// 默认采用字符串解析
				result[i++] = null;
			}
		}
		return result;
	}

}
